<?php
/*
* Kusht Mud.
* ----
* The MIT License
* Copyright (c) 2010 Andrew Tutt
* ----
*/

/* DB Handler
*
* Functions Regarding Database Interactions and Abstraction
* 
* Provides the Crucial Bridge Layer Between "The Game" and the Database
* Architecture (This is our "Glue")
*/

/* Currently implementing a MySQL database */
class dbHandler {

	public static $link;

	public static function connect($hostname, $username, $pass) {
		dbHandler::$link = mysqli_connect($hostname, $username, $pass);
		mysqli_select_db(dbHandler::$link,"kusht") or die( "Unable to select database");
		if (!dbHandler::is_installed()) { dbHandler::install_db(); }		
	}

	// Of course, everything above is aspirational. ;)
	public static function loadGame() {
		dbHandler::loadRooms();
		World::sortRooms();
		echo "---\nDatabase Loaded";
	}
	
	public static function save($object) {
		// We are passed any in-game object, and we save it by
		// Retrieving it's class and tossing it off to its own specific saver
		$class = get_class($object);
		$func_name = "save".$class;
		dbHandler::$func_name($object);
	}
	
	public static function load($object, $id) {
		// We are passed any in-game object, and we load it by
		// Retrieving it's class and tossing it off to its own specific loader
		$class = get_class($object);
		$func_name = "load".$class;
		$object = dbHandler::$func_name($id);
		return $object;
	}
	
	public static function delete($object) {
		// We are passed any in-game object, and we delete it by
		// Retrieving it's class and tossing it off to its own specific deleter
		$id = $object->id;
		$class = get_class($object);
		$func_name = "delete".$class;
		dbHandler::$func_name($id);
	}
	
	public static function loadRooms() {
		$query="SELECT id FROM rooms";
		$result = mysqli_query(dbHandler::$link,$query);
		
		while ($row = mysqli_fetch_row($result)) {
        	$room = dbHandler::loadstartupRoom($row[0]);
			array_push(World::$room_list,$room);
    	}
		
		dbHandler::loadExits_();
	}
	
	public static function loadstartupRoom($id) {
		$room = new Room();
		set_fields_equal($room,dbHandler::loadBaseObject($id));
		return $room;
	}
	
	// 	$query = "SELECT * FROM baseobjects,exits WHERE baseobjects.in_object_id='$id' AND baseobjects.id = exits.id";
	public static function loadRoom($id) {
		$room = new Room();
		set_fields_equal($room,dbHandler::loadBaseObject($id));
		dbHandler::loadRoomExits_($room);
		return $room;
	}
	
	public static function loadRoomExits_($room) {
		$id = $room->id;
		$query = "SELECT * FROM baseobjects,exits WHERE baseobjects.in_object_id='$id' AND baseobjects.id = exits.id";
		$result = mysqli_query(dbHandler::$link,$query) or die("Bad Query @ loadRoomExit");
		
		
		while ($row = mysqli_fetch_row($result)) {
        	$exit = dbHandler::loadExit_($row[0]);
			$in_room = $room;
			$exit->to_room = get_obj_by_field_value($exit->to_room_id,"id",World::$room_list);
			array_push($in_room->exits,$exit);
    	}
	}
	
	public static function saveRoom($room) {
		// We are going to be inserting a new BaseObject that represents this room's Information
		dbHandler::saveBaseObject($room);
		// Now we save the room as a room
		$query="INSERT INTO rooms (id) VALUES ('$room->id')";
		mysqli_query(dbHandler::$link,$query);
		// Now we save the exits as exits
		foreach($room->exits as $exit) {
			dbHandler::saveExit_($exit,$room);
		}
		
	}
	
	// Run once on startup
	public static function loadExits_() {
		$query = "SELECT id FROM exits";
		$result = mysqli_query(dbHandler::$link,$query); 
		
		while ($row = mysqli_fetch_row($result)) {
        	$exit = dbHandler::loadExit_($row[0]);
			$in_room = get_obj_by_field_value($exit->in_object_id,"id",World::$room_list);
			$exit->to_room = get_obj_by_field_value($exit->to_room_id,"id",World::$room_list);
			array_push($in_room->exits,$exit);
    	}
	}
	
	public static function loadExit_($id) {
		$exit = new Exit_();
		set_fields_equal($exit,dbHandler::loadBaseObject($id));
		$query = "SELECT * FROM exits WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query); 
		$obj = mysqli_fetch_object($result);
		set_fields_equal($exit,$obj);		
		return $exit;
	}
	
	public static function saveExit_($exit,$room) {
		$exit->in_object = $room; // Just to be certain
		dbHandler::saveBaseObject($exit);
		add_slashes_object($exit);
		
		if (!isset($exit->to_room->id) || $exit->to_room->id==DEF_NEG) {
			dbHandler::saveRoom($exit->to_room);
		}
		
		// Prep a couple longer chains for query
		$tmp1 = $exit->to_room->id;
		// Query String
		$query="INSERT INTO exits (id,tellUser,tellOthers,command,commandtgt,to_room_id) 
		VALUES ('$exit->id', '$exit->tellUser', '$exit->tellOthers', '$exit->command', '$exit->commandtgt',
		'$tmp1')
		ON DUPLICATE KEY UPDATE tellUser=VALUES(tellUser), tellOthers=VALUES(tellOthers), command=VALUES(command),
		commandtgt=VALUES(commandtgt), to_room_id=VALUES(to_room_id)";
		mysqli_query(dbHandler::$link,$query);
		// Remove Slashes
		rmv_slashes_object($exit);
	}
	
	public static function deleteExit_($id) {
		$query = "DELETE FROM exits WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query) or die("Unable to delete Exit from exit table"); 
		$query = "DELETE FROM baseobjects WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query) or die("Unable to delete Exit from baseobjects table"); 
	}
	
	public static function saveItem($item) {
		dbHandler::saveBaseObject($item);
		$query="INSERT INTO items (id) VALUES ($item->id)";
		mysqli_query(dbHandler::$link,$query);
	}
	
	public static function loadBaseObject($id) {
		$query = "SELECT * FROM baseobjects WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query); 
		$obj = mysqli_fetch_object($result);
		$object = new BaseObject();
		set_fields_equal($object,$obj);
		dbHandler::loadFlags($object);
		return $object;
	}
	
	public static function saveBaseObject($object) {
		add_slashes_object($object);
		// Long Chains
		if(!isset($object->in_object)) { $container_id = DEF_NEG; }
		else { $container_id = $object->in_object->id; }
		// Query
		if(isset($object->id) && ($object->id != DEF_NEG)) {
			$query="UPDATE baseobjects SET name='$object->name', 
									short_descr='$object->short_descr',
									description='$object->description',
									 	  thumb='$object->thumb',
									 	  image='$object->image',
								   in_object_id='$container_id',
								   		 weight='$object->weight', 
								 execute_interval='$object->execute_interval', 
								   	 execute_code='$object->execute_code' where id='$object->id'";
			mysqli_query(dbHandler::$link,$query);
		} else {
			$query="INSERT INTO baseobjects (name, short_descr,	description, thumb, image, weight, in_object_id, execute_interval, execute_code) 
				VALUES ('$object->name', '$object->short_descr', '$object->description', '$object->thumb', '$object->image', '$object->weight', '$container_id',
				'$object->execute_interval','$object->execute_code')";
				mysqli_query(dbHandler::$link,$query);
				// But we need to know what Primary Key it had
				$object->id = mysqli_insert_id(dbHandler::$link);
		}
		
		// Send its Flags to the Flags table
		dbHandler::saveFlags($object);
		
		// Remove Slashes
		rmv_slashes_object($object);
	}
	
	public static function saveFlags($object) {
		if(!isset($object->all_flags)) { return; }
		
		foreach($object->all_flags as $k=>$e) {
			$query = "INSERT INTO flags (id, flag, byte_num) VALUES ('$object->id', '$e', '$k')";
			mysqli_query(dbHandler::$link,$query) or die('Bad query text');
		}
	}
	
	public static function loadFlags($object) {
		$query = "SELECT * FROM flags WHERE id='$object->id'";
		$result = mysqli_query(dbHandler::$link,$query);
		
		while ($row = mysqli_fetch_row($result)) {
			$object->all_flags[$row[3]] = $row[2];
		}
	}
	
	/* ------------ LOGIN ACCOUNT ----------------- */
	
	public static function charExists($name) {
		$query = "SELECT * FROM user_characters, baseobjects WHERE baseobjects.name='$name'";
		return mysqli_num_rows(mysqli_query(dbHandler::$link,$query));
	}
	
	public static function loadUserAccount($id) {
		$query = "SELECT * FROM user_accounts WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query);
		if(mysqli_num_rows($result)==0) { return false; }
		return mysqli_fetch_object($result);
	}
	
	public static function saveUserAccount($id,$password,$email) {
		$query = "INSERT INTO user_accounts (id, password, email) VALUES
			('$id','$password','$email')";
		$result = mysqli_query(dbHandler::$link,$query);
	}
	
	public static function loadUserCharacters($id) {
		$query = "SELECT * FROM user_characters WHERE owner_id='$id'";
		$result = mysqli_query(dbHandler::$link,$query);
		if(mysqli_num_rows($result)==0) { return false; }
		$tmp = array();
		$i = 0;
		while ($row = mysqli_fetch_row($result)) {
			$tmp += array($i=>array("id"=>$row[0]));
			$i++;
		}
		return $tmp;
	}
	
	// To be updated and expanded
	public static function loadUserCharacter($id) {
		$tmp = new UserCharacter();
		$obj = dbHandler::loadBaseObject($id);
		set_fields_equal($tmp,$obj);
		$query = "SELECT * FROM user_characters WHERE id='$id'";
		$result = mysqli_query(dbHandler::$link,$query);
		$obj = mysqli_fetch_object($result);
		set_fields_equal($tmp,$obj);
		return $tmp;
	}
		
	// This function will need to be updated and expanded
	public static function saveUserCharacter($userchar) {
		dbHandler::saveBaseObject($userchar);
		$query = "INSERT INTO user_characters (id, owner_id) VALUES ('$userchar->id','$userchar->owner_id')";
		mysqli_query(dbHandler::$link,$query);
	}
	
	/* ------------ INSTALLATION STUFF ------------ */
	
	function is_installed() {
		$installed = mysqli_query(dbHandler::$link, "SELECT * FROM installed" );
		if ( $installed ) { return true; }		
	}
	
	public static function delete_db() {
		mysqli_query(dbHandler::$link,"DROP DATABASE kusht");
		mysqli_query(dbHandler::$link,"CREATE DATABASE kusht");
		mysqli_select_db(dbHandler::$link,"kusht") or die( "Unable to select database");
	}
	
	/* All game objects' IDs are based on the unique ID Assigned
	   by baseobject table */
	public static function install_db() {
		// Create the BaseObjects Table
		$query="CREATE TABLE baseobjects (
				id 				int(6) 		NOT NULL auto_increment,
				name			TINYTEXT	NOT NULL,
				short_descr		TEXT		NOT NULL,
				description		TEXT		NOT NULL,
				thumb			TINYTEXT	NOT NULL,
				image			TINYTEXT	NOT NULL,
				weight			SMALLINT	NOT NULL,
				in_object_id	int(6)		NOT NULL,
				execute_interval	INT			NOT NULL,
				execute_code		TEXT		NOT NULL,

				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table baseobjects created.\n";
		}; 

		// Create the Items Table
		$query="CREATE TABLE items (
				id 				int(6) 		NOT NULL,

				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table items created.\n";
		}; 

		
		// Create the Flags Table
		$query="CREATE TABLE flags (
				flag_id			int(6) 		NOT NULL auto_increment,
				id				int(6)		NOT NULL,
				flag			INT			NOT NULL,
				byte_num		int(6)		NOT NULL,
				
				PRIMARY KEY 			(flag_id),
				UNIQUE 			flag_id	(flag_id),
				KEY 			id_2 	(flag_id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table flags created.\n";
		}; 
	
		// Create the Rooms Table
		$query="CREATE TABLE rooms (
				id 				int(6) 		NOT NULL,
				sector			TINYTEXT	NOT NULL,	
				
				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table rooms created.\n";
		}; 
		
		// Create the Exits Table
		$query="CREATE TABLE exits (
				id 				int(6) 		NOT NULL,
				tellUser		TINYTEXT	NOT NULL,
				tellOthers		TINYTEXT	NOT NULL,
				command			TINYTEXT	NOT NULL,
				commandtgt		TINYTEXT	NOT NULL,
				to_room_id		int(6)		NOT NULL,
				
				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table exits created.\n";
		}; 
		
		// Create the User Accounts Table
		$query="CREATE TABLE user_accounts (
				id			varchar(20) NOT NULL,
				password	varchar(20) NOT NULL,
				email 		varchar(30) NOT NULL,
				
				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table user_accounts created.\n";
		}; 
		
		// Create the User Character Table
		$query="CREATE TABLE user_characters (
				id 				int(6) 		NOT NULL,
				owner_id		varchar(20)	NOT NULL,
				
				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table user_characters created.\n";
		}; 
		
		// Create the Meta Text Table
		// Meta Text is notes, help files, ideas, etc.
		// Human Readable: SELECT DATE_FORMAT(timestamp,'%l:%i:%s %p on %M %D, %Y') AS ... FROM ... WHERE ...
		$query="CREATE TABLE meta_text (
				id 				int(6) 		NOT NULL auto_increment,
				type			INT			NOT NULL,
				topic			TINYTEXT	NOT NULL,
				author			TINYTEXT	NOT NULL,
				keywords		TINYTEXT	NOT NULL,
				firstposted		TIMESTAMP	DEFAULT NOW(),
				lastrevised		TIMESTAMP,
				content			TEXT		NOT NULL,
				
				PRIMARY KEY 			(id),
				UNIQUE 			id 		(id),
				KEY 			id_2 	(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table meta_text created.\n";
		}; 
		
		// Create the BaseObject Instances Table
		$query="CREATE TABLE baseobject_instances (
				instance_id		int(6)		NOT NULL auto_increment,
				name			TINYTEXT	NOT NULL,
				short_descr		TEXT		NOT NULL,
				description		TEXT		NOT NULL,
				thumb			TINYTEXT	NOT NULL,
				image			TINYTEXT	NOT NULL,
				weight			SMALLINT	NOT NULL,
				in_object_id	int(6)		NOT NULL,

				PRIMARY KEY 					(instance_id),
				UNIQUE 			instance_id 	(instance_id),
				KEY 			id_2 			(instance_id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table baseobject_instances created.\n";
		}; 
		
		// Create the Item Instances Table
		$query="CREATE TABLE item_instances (
				instance_id 	int(6) 		NOT NULL,

				PRIMARY KEY 					(instance_id),
				UNIQUE 			instance_id 	(instance_id),
				KEY 			id_2 			(instance_id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Table item_instances created.\n";
		}; 
	
		// Create an "installed" table to verify installation
		$query="CREATE TABLE installed (
				id 			int(6) 		NOT NULL auto_increment,
				
				PRIMARY KEY 			(id))";
		if (mysqli_query(dbHandler::$link,$query) === TRUE) {
			echo "Database Installed.\n\n";
		}; 
	}
}

?>